package me.leon.encode.base

import me.leon.ext.math.toBigInteger
import me.leon.ext.toUnicodeChar

/**
 * @author Leon
 * @since 2022-10-31 10:49
 */
private const val PADDING = 9_749
private const val PADDING_40 = 9_884
private const val PADDING_41 = 127_949
private const val PADDING_42 = 128_209
private const val PADDING_43 = 128_587

private val PADDING4 = intArrayOf(PADDING_40, PADDING_41, PADDING_42, PADDING_43)
val MAPPING =
    intArrayOf(
        126_980,
        127_183,
        127_344,
        127_345,
        127_358,
        127_359,
        127_374,
        127_377,
        127_378,
        127_379,
        127_380,
        127_381,
        127_382,
        127_383,
        127_384,
        127_385,
        127_386,
        127_462,
        127_463,
        127_464,
        127_465,
        127_466,
        127_467,
        127_468,
        127_469,
        127_470,
        127_471,
        127_472,
        127_473,
        127_474,
        127_475,
        127_476,
        127_477,
        127_478,
        127_479,
        127_480,
        127_481,
        127_482,
        127_483,
        127_484,
        127_485,
        127_486,
        127_487,
        127_489,
        127_490,
        127_514,
        127_535,
        127_538,
        127_539,
        127_540,
        127_541,
        127_542,
        127_543,
        127_544,
        127_545,
        127_546,
        127_568,
        127_569,
        127_744,
        127_745,
        127_746,
        127_747,
        127_748,
        127_749,
        127_750,
        127_751,
        127_752,
        127_753,
        127_754,
        127_755,
        127_756,
        127_757,
        127_758,
        127_759,
        127_760,
        127_761,
        127_762,
        127_763,
        127_764,
        127_765,
        127_766,
        127_767,
        127_768,
        127_769,
        127_770,
        127_771,
        127_772,
        127_773,
        127_774,
        127_775,
        127_776,
        127_777,
        127_780,
        127_781,
        127_782,
        127_783,
        127_784,
        127_785,
        127_786,
        127_787,
        127_788,
        127_789,
        127_790,
        127_791,
        127_792,
        127_793,
        127_794,
        127_795,
        127_796,
        127_797,
        127_798,
        127_799,
        127_800,
        127_801,
        127_802,
        127_803,
        127_804,
        127_805,
        127_806,
        127_807,
        127_808,
        127_809,
        127_810,
        127_811,
        127_812,
        127_813,
        127_814,
        127_815,
        127_816,
        127_817,
        127_818,
        127_819,
        127_820,
        127_821,
        127_822,
        127_823,
        127_824,
        127_825,
        127_826,
        127_827,
        127_828,
        127_829,
        127_830,
        127_831,
        127_832,
        127_833,
        127_834,
        127_835,
        127_836,
        127_837,
        127_838,
        127_839,
        127_840,
        127_841,
        127_842,
        127_843,
        127_844,
        127_845,
        127_846,
        127_847,
        127_848,
        127_849,
        127_850,
        127_851,
        127_852,
        127_853,
        127_854,
        127_855,
        127_856,
        127_857,
        127_858,
        127_859,
        127_860,
        127_861,
        127_862,
        127_863,
        127_864,
        127_865,
        127_866,
        127_867,
        127_868,
        127_869,
        127_870,
        127_871,
        127_872,
        127_873,
        127_874,
        127_875,
        127_876,
        127_877,
        127_878,
        127_879,
        127_880,
        127_881,
        127_882,
        127_883,
        127_884,
        127_885,
        127_886,
        127_887,
        127_888,
        127_889,
        127_890,
        127_891,
        127_894,
        127_895,
        127_897,
        127_898,
        127_899,
        127_902,
        127_903,
        127_904,
        127_905,
        127_906,
        127_907,
        127_908,
        127_909,
        127_910,
        127_911,
        127_912,
        127_913,
        127_914,
        127_915,
        127_916,
        127_917,
        127_918,
        127_919,
        127_920,
        127_921,
        127_922,
        127_923,
        127_924,
        127_925,
        127_926,
        127_927,
        127_928,
        127_929,
        127_930,
        127_931,
        127_932,
        127_933,
        127_934,
        127_935,
        127_936,
        127_937,
        127_938,
        127_939,
        127_940,
        127_941,
        127_942,
        127_943,
        127_944,
        127_945,
        127_946,
        127_947,
        127_948,
        127_950,
        127_951,
        127_952,
        127_953,
        127_954,
        127_955,
        127_956,
        127_957,
        127_958,
        127_959,
        127_960,
        127_961,
        127_962,
        127_963,
        127_964,
        127_965,
        127_966,
        127_967,
        127_968,
        127_969,
        127_970,
        127_971,
        127_972,
        127_973,
        127_974,
        127_975,
        127_976,
        127_977,
        127_978,
        127_979,
        127_980,
        127_981,
        127_982,
        127_983,
        127_984,
        127_987,
        127_988,
        127_989,
        127_991,
        127_992,
        127_993,
        127_994,
        127_995,
        127_996,
        127_997,
        127_998,
        127_999,
        128_000,
        128_001,
        128_002,
        128_003,
        128_004,
        128_005,
        128_006,
        128_007,
        128_008,
        128_009,
        128_010,
        128_011,
        128_012,
        128_013,
        128_014,
        128_015,
        128_016,
        128_017,
        128_018,
        128_019,
        128_020,
        128_021,
        128_022,
        128_023,
        128_024,
        128_025,
        128_026,
        128_027,
        128_028,
        128_029,
        128_030,
        128_031,
        128_032,
        128_033,
        128_034,
        128_035,
        128_036,
        128_037,
        128_038,
        128_039,
        128_040,
        128_041,
        128_042,
        128_043,
        128_044,
        128_045,
        128_046,
        128_047,
        128_048,
        128_049,
        128_050,
        128_051,
        128_052,
        128_053,
        128_054,
        128_055,
        128_056,
        128_057,
        128_058,
        128_059,
        128_060,
        128_061,
        128_062,
        128_063,
        128_064,
        128_065,
        128_066,
        128_067,
        128_068,
        128_069,
        128_070,
        128_071,
        128_072,
        128_073,
        128_074,
        128_075,
        128_076,
        128_077,
        128_078,
        128_079,
        128_080,
        128_081,
        128_082,
        128_083,
        128_084,
        128_085,
        128_086,
        128_087,
        128_088,
        128_089,
        128_090,
        128_091,
        128_092,
        128_093,
        128_094,
        128_095,
        128_096,
        128_097,
        128_098,
        128_099,
        128_100,
        128_101,
        128_102,
        128_103,
        128_104,
        128_105,
        128_106,
        128_107,
        128_108,
        128_109,
        128_110,
        128_111,
        128_112,
        128_113,
        128_114,
        128_115,
        128_116,
        128_117,
        128_118,
        128_119,
        128_120,
        128_121,
        128_122,
        128_123,
        128_124,
        128_125,
        128_126,
        128_127,
        128_128,
        128_129,
        128_130,
        128_131,
        128_132,
        128_133,
        128_134,
        128_135,
        128_136,
        128_137,
        128_138,
        128_139,
        128_140,
        128_141,
        128_142,
        128_143,
        128_144,
        128_145,
        128_146,
        128_147,
        128_148,
        128_149,
        128_150,
        128_151,
        128_152,
        128_153,
        128_154,
        128_155,
        128_156,
        128_157,
        128_158,
        128_159,
        128_160,
        128_161,
        128_162,
        128_163,
        128_164,
        128_165,
        128_166,
        128_167,
        128_168,
        128_169,
        128_170,
        128_171,
        128_172,
        128_173,
        128_174,
        128_175,
        128_176,
        128_177,
        128_178,
        128_179,
        128_180,
        128_181,
        128_182,
        128_183,
        128_184,
        128_185,
        128_186,
        128_187,
        128_188,
        128_189,
        128_190,
        128_191,
        128_192,
        128_193,
        128_194,
        128_195,
        128_196,
        128_197,
        128_198,
        128_199,
        128_200,
        128_201,
        128_202,
        128_203,
        128_204,
        128_205,
        128_206,
        128_207,
        128_208,
        128_210,
        128_211,
        128_212,
        128_213,
        128_214,
        128_215,
        128_216,
        128_217,
        128_218,
        128_219,
        128_220,
        128_221,
        128_222,
        128_223,
        128_224,
        128_225,
        128_226,
        128_227,
        128_228,
        128_229,
        128_230,
        128_231,
        128_232,
        128_233,
        128_234,
        128_235,
        128_236,
        128_237,
        128_238,
        128_239,
        128_240,
        128_241,
        128_242,
        128_243,
        128_244,
        128_245,
        128_246,
        128_247,
        128_248,
        128_249,
        128_250,
        128_251,
        128_252,
        128_253,
        128_255,
        128_256,
        128_257,
        128_258,
        128_259,
        128_260,
        128_261,
        128_262,
        128_263,
        128_264,
        128_265,
        128_266,
        128_267,
        128_268,
        128_269,
        128_270,
        128_271,
        128_272,
        128_273,
        128_274,
        128_275,
        128_276,
        128_277,
        128_278,
        128_279,
        128_280,
        128_281,
        128_282,
        128_283,
        128_284,
        128_285,
        128_286,
        128_287,
        128_288,
        128_289,
        128_290,
        128_291,
        128_292,
        128_293,
        128_294,
        128_295,
        128_296,
        128_297,
        128_298,
        128_299,
        128_300,
        128_301,
        128_302,
        128_303,
        128_304,
        128_305,
        128_306,
        128_307,
        128_308,
        128_309,
        128_310,
        128_311,
        128_312,
        128_313,
        128_314,
        128_315,
        128_316,
        128_317,
        128_329,
        128_330,
        128_331,
        128_332,
        128_333,
        128_334,
        128_336,
        128_337,
        128_338,
        128_339,
        128_340,
        128_341,
        128_342,
        128_343,
        128_344,
        128_345,
        128_346,
        128_347,
        128_348,
        128_349,
        128_350,
        128_351,
        128_352,
        128_353,
        128_354,
        128_355,
        128_356,
        128_357,
        128_358,
        128_359,
        128_367,
        128_368,
        128_371,
        128_372,
        128_373,
        128_374,
        128_375,
        128_376,
        128_377,
        128_378,
        128_391,
        128_394,
        128_395,
        128_396,
        128_397,
        128_400,
        128_405,
        128_406,
        128_420,
        128_421,
        128_424,
        128_433,
        128_434,
        128_444,
        128_450,
        128_451,
        128_452,
        128_465,
        128_466,
        128_467,
        128_476,
        128_477,
        128_478,
        128_481,
        128_483,
        128_488,
        128_495,
        128_499,
        128_506,
        128_507,
        128_508,
        128_509,
        128_510,
        128_511,
        128_512,
        128_513,
        128_514,
        128_515,
        128_516,
        128_517,
        128_518,
        128_519,
        128_520,
        128_521,
        128_522,
        128_523,
        128_524,
        128_525,
        128_526,
        128_527,
        128_528,
        128_529,
        128_530,
        128_531,
        128_532,
        128_533,
        128_534,
        128_535,
        128_536,
        128_537,
        128_538,
        128_539,
        128_540,
        128_541,
        128_542,
        128_543,
        128_544,
        128_545,
        128_546,
        128_547,
        128_548,
        128_549,
        128_550,
        128_551,
        128_552,
        128_553,
        128_554,
        128_555,
        128_556,
        128_557,
        128_558,
        128_559,
        128_560,
        128_561,
        128_562,
        128_563,
        128_564,
        128_565,
        128_566,
        128_567,
        128_568,
        128_569,
        128_570,
        128_571,
        128_572,
        128_573,
        128_574,
        128_575,
        128_576,
        128_577,
        128_578,
        128_579,
        128_580,
        128_581,
        128_582,
        128_583,
        128_584,
        128_585,
        128_586,
        128_588,
        128_589,
        128_590,
        128_591,
        128_640,
        128_641,
        128_642,
        128_643,
        128_644,
        128_645,
        128_646,
        128_647,
        128_648,
        128_649,
        128_650,
        128_651,
        128_652,
        128_653,
        128_654,
        128_655,
        128_656,
        128_657,
        128_658,
        128_659,
        128_660,
        128_661,
        128_662,
        128_663,
        128_664,
        128_665,
        128_666,
        128_667,
        128_668,
        128_669,
        128_670,
        128_671,
        128_672,
        128_673,
        128_674,
        128_675,
        128_676,
        128_677,
        128_678,
        128_679,
        128_680,
        128_681,
        128_682,
        128_683,
        128_684,
        128_685,
        128_686,
        128_687,
        128_688,
        128_689,
        128_690,
        128_691,
        128_692,
        128_693,
        128_694,
        128_695,
        128_696,
        128_697,
        128_698,
        128_699,
        128_700,
        128_701,
        128_702,
        128_703,
        128_704,
        128_705,
        128_706,
        128_707,
        128_708,
        128_709,
        128_715,
        128_716,
        128_717,
        128_718,
        128_719,
        128_720,
        128_721,
        128_722,
        128_736,
        128_737,
        128_738,
        128_739,
        128_740,
        128_741,
        128_745,
        128_747,
        128_748,
        128_752,
        128_755,
        128_756,
        128_757,
        128_758,
        128_759,
        128_760,
        128_761,
        129_296,
        129_297,
        129_298,
        129_299,
        129_300,
        129_301,
        129_302,
        129_303,
        129_304,
        129_305,
        129_306,
        129_307,
        129_308,
        129_309,
        129_310,
        129_311,
        129_312,
        129_313,
        129_314,
        129_315,
        129_316,
        129_317,
        129_318,
        129_319,
        129_320,
        129_321,
        129_322,
        129_323,
        129_324,
        129_325,
        129_326,
        129_327,
        129_328,
        129_329,
        129_330,
        129_331,
        129_332,
        129_333,
        129_334,
        129_335,
        129_336,
        129_337,
        129_338,
        129_340,
        129_341,
        129_342,
        129_344,
        129_345,
        129_346,
        129_347,
        129_348,
        129_349,
        129_351,
        129_352,
        129_353,
        129_354,
        129_355,
        129_356,
        129_357,
        129_358,
        129_359,
        129_360,
        129_361,
        129_362,
        129_363,
        129_364,
        129_365,
        129_366,
        129_367,
        129_368,
        129_369,
        129_370,
        129_371,
        129_372,
        129_373,
        129_374,
        129_375,
        129_376,
        129_377,
        129_378,
        129_379,
        129_380,
        129_381,
        129_382,
        129_383,
        129_384,
        129_385,
        129_386,
        129_387,
        129_388,
        129_389,
        129_390,
        129_391,
        129_392,
        129_395,
        129_396,
        129_397,
        129_398,
        129_402,
        129_404,
        129_405,
        129_406,
        129_407,
        129_408,
        129_409,
        129_410,
        129_411,
        129_412,
        129_413,
        129_414,
        129_415,
        129_416,
        129_417,
        129_418,
        129_419,
        129_420,
        129_421,
        129_422,
        129_423,
        129_424,
        129_425,
        129_426,
        129_427,
        129_428,
        129_429,
        129_430,
        129_431,
        129_432,
        129_433,
        129_434,
        129_435,
        129_436,
        129_437,
        129_438,
        129_439,
        129_440,
        129_441,
        129_442,
        129_456,
        129_457,
        129_458,
        129_459,
        129_460,
        129_461,
        129_462,
        129_463,
        129_464,
        129_465,
        129_472,
        129_473,
        129_474,
        129_488,
        129_489,
        129_490,
        129_491,
        129_492,
        129_493,
    )

fun revMapGetOrZero(k: Int): Int {
    val index = MAPPING.indexOf(k)
    return if (index < 0) 0 else index
}

fun String.ecoji(): String = toByteArray().ecoji()

fun ByteArray.ecoji(): String {
    return asIterable().chunked(5).joinToString("") {
        var b0 = 0
        var b1 = 0
        var b2 = 0
        var b3 = 0
        var b4 = 0
        when (it.size) {
            5 -> {
                b4 = it[4].toUInt().toInt()
                b3 = it[3].toUInt().toInt()
                b2 = it[2].toUInt().toInt()
                b1 = it[1].toUInt().toInt()
                b0 = it[0].toUInt().toInt()
            }
            4 -> {
                b3 = it[3].toUInt().toInt()
                b2 = it[2].toUInt().toInt()
                b1 = it[1].toUInt().toInt()
                b0 = it[0].toUInt().toInt()
            }
            3 -> {
                b2 = it[2].toUInt().toInt()
                b1 = it[1].toUInt().toInt()
                b0 = it[0].toUInt().toInt()
            }
            2 -> {
                b1 = it[1].toUInt().toInt()
                b0 = it[0].toUInt().toInt()
            }
            1 -> b0 = it[0].toUInt().toInt()
            else -> {}
        }
        val chars = intArrayOf(MAPPING[b0 shl 2 or (b1 shr 6)], PADDING, PADDING, PADDING)
        when (it.size) {
            5,
            4,
            3 -> {
                chars[2] = MAPPING[b2 and 0x0f shl 6 or (b3 shr 2)]
                chars[1] = MAPPING[b1 and 0x3f shl 4 or (b2 shr 4)]
            }
            2 -> chars[1] = MAPPING[b1 and 0x3f shl 4 or (b2 shr 4)]
            else -> {}
        }
        if (it.size == 4) {
            when (b3 and 0x03) {
                0 -> chars[3] = PADDING_40
                1 -> chars[3] = PADDING_41
                2 -> chars[3] = PADDING_42
                3 -> chars[3] = PADDING_43
                else -> {}
            }
        } else if (it.size == 5) {
            chars[3] = MAPPING[b3 and 0x03 shl 8 or b4]
        }
        chars.joinToString("") { it.toUnicodeChar() }
    }
}

fun String.ecojiDecode(): ByteArray {
    return toByteArray(Charsets.UTF_32BE)
        .asIterable()
        .chunked(16)
        .map {
            val chars = it.chunked(4).map { it.toByteArray().toBigInteger().toInt() }
            val len =
                if (chars[1] == PADDING) {
                    1
                } else if (chars[2] == PADDING) {
                    2
                } else if (chars[3] == PADDING) {
                    3
                } else if (PADDING4.contains(chars[3])) {
                    4
                } else {
                    5
                }
            val ints =
                it.chunked(4).mapIndexed { index, bytes ->
                    val emojiInt = bytes.toByteArray().toBigInteger().toInt()
                    if (index == 3) {
                        when (emojiInt) {
                            PADDING_40 -> 0
                            PADDING_41 -> 1 shl 8
                            PADDING_42 -> 2 shl 8
                            PADDING_43 -> 3 shl 8
                            else -> revMapGetOrZero(emojiInt)
                        }
                    } else {
                        revMapGetOrZero(emojiInt)
                    }
                }
            byteArrayOf(
                    (ints[0] shr 2).toByte(),
                    (ints[0] and 0x3 shl 6 or (ints[1] shr 4)).toByte(),
                    (ints[1] and 0xf shl 4 or (ints[2] shr 6)).toByte(),
                    (ints[2] and 0x3f shl 2 or (ints[3] shr 8)).toByte(),
                    (ints[3] and 0xff).toByte(),
                )
                .take(len)
        }
        .flatten()
        .toByteArray()
}

fun String.ecojiDecode2String() = ecojiDecode().decodeToString()
